package com.itheima.stock.service.impl;

import com.itheima.stock.cache.Cache;
import com.itheima.stock.constant.Constants;
import com.itheima.stock.dto.LoginDTO;
import com.itheima.stock.entity.SysUser;
import com.itheima.stock.enums.CodeEnum;
import com.itheima.stock.exception.Exceptions;
import com.itheima.stock.mapper.SysUserMapper;
import com.itheima.stock.service.UserService;
import com.itheima.stock.util.IdWorkers;
import com.itheima.stock.util.RedisKeyUtil;
import com.itheima.stock.vo.CaptchaVO;
import com.itheima.stock.vo.LoginVO;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

/**
 * @author zby
 * @created 2024-06-25 11:14
 * @description 用户服务接口实现
 */
@Service
public class UserServiceImpl implements UserService {

    private final IdWorkers idWorkers;

    private final Cache cache;

    private final SysUserMapper sysUserMapper;

    private final PasswordEncoder passwordEncoder;

    /**
     * 定义随机数的位数
     */
    private static final int FOUR = 4;

    public UserServiceImpl(Cache cache, IdWorkers idWorkers, SysUserMapper sysUserMapper, PasswordEncoder passwordEncoder) {
        this.cache = cache;
        this.idWorkers = idWorkers;
        this.sysUserMapper = sysUserMapper;
        this.passwordEncoder = passwordEncoder;
    }


    @Override
    public LoginVO login(LoginDTO dto) {
        // 1. 参数校验
        if(ObjectUtils.isEmpty(dto)
                || ObjectUtils.isEmpty(dto.getUsername())
                || ObjectUtils.isEmpty(dto.getPassword())
                || ObjectUtils.isEmpty(dto.getCode())
                || ObjectUtils.isEmpty(dto.getRkey())){
            Exceptions.cast(CodeEnum.PARAM_IS_NOT_NULL);
        }
        // 2.核心登录逻辑
        // 2.1 首先用前端传递的验证码和 redis中存储验证码进行比较，一致查询数据库 否则提示验证码错误
        String captchaInRedis = cache.get(dto.getRkey());
        if (!StringUtils.equals(captchaInRedis, dto.getCode())) {
            Exceptions.cast(CodeEnum.SYSTEM_VERIFY_CODE_ERROR);
        }
        // 2.2 根据用户名（隐藏条件）查询数据库
        SysUser user = sysUserMapper.selectByUsername(dto.getUsername(),Constants.SYS_USER_STATUS_NORMAL,Constants.SYS_USER_UN_DELETE);
        // 2.3 判断用户是否存在,判断密码是否正确
        if(ObjectUtils.isEmpty(user) || !passwordEncoder.matches(dto.getPassword(), user.getPassword()) ){
            Exceptions.cast(CodeEnum.SYSTEM_USERNAME_NOT_EXISTS);
        }
        // 删除Redis 中的验证码
        cache.remove(dto.getRkey());
        // 3. 数据组装返回
        return LoginVO.builder()
                .id(user.getId())
                .username(user.getUsername())
                .nickName(user.getNickName())
                .phone(user.getPhone())
                .build();
    }

    @Override
    public CaptchaVO captcha() {
        //1. 生成随机4位验证码
        String captcha = RandomStringUtils.randomNumeric(FOUR);
        //2. 将验证码存储到Redis（key设计、 架构设计）
        // 2.1 生成Redis的key
        String redisKey = RedisKeyUtil.generateKey(Constants.CAPTCHA_PREFIX, idWorkers.nextStrId());
        // 2.2 调用缓存接口存入验证码
        cache.set(redisKey, captcha, Constants.CAPTCHA_EXPIRE_TIME);
        // 3. 数据组装返回
        return CaptchaVO.builder()
                .rkey(redisKey)
                .code(captcha)
                .build();
    }
}
